#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/fs.h>
#include <stdlib.h>
#include <stdint.h>

// 定义超级块结构
struct ext_super_block {
    __le32 s_inodes_count;        // inode节点数
    __le32 s_blocks_count;        // 总块数
    __le32 s_r_blocks_count;      //可用块数
    __le32 s_free_blocks_count;   //空闲块数
    __le32 s_free_inodes_count;   //可用inode计数器
    __le32 s_first_data_block;    //第一个有用块数
    __le32 s_log_block_size;      //块大小
    __le32 s_log_frag_size;       //片段大小
    __le32 s_blocks_per_group;    //每组块数
    __le32 s_frags_per_group;     //每组的片段数
    __le32 s_inodes_per_group;    //每组的inode节点数
};

// 定义组描述符表结构
struct ext_group_desc {
    __le32 bg_block_bitmap_lo;      // 块位图所在块号
    __le32 bg_inode_bitmap_lo;      //索引节点位图的块数
    __le32 bg_inode_table_lo;       // 第一个inode表块的块号
    __le16 bg_free_blocks_count_lo; //组中的可用块数
    __le16 bg_free_inodes_count_lo; //组中空闲索引节点的数量
    __le16 bg_used_dirs_count_lo;   //组中的目录数
};


// 定义inode结构体
struct ext_inode {
    __le16  i_mode;         // 文件模式
    __le16  i_uid;          // 用户ID
    __le32  i_size_lo;      // 文件大小
};

//位图打印函数
void printBitmap(const void* data, size_t size) {
    const unsigned char* buffer = (const unsigned char*)data;
    size_t i, j;
    int allZeroLine = 1;
    int allFFLine = 1;

    for (i = 0; i < size; i += 16) {
        allZeroLine = 1;
        allFFLine = 1;

        for (j = 0; j < 16; ++j) {
            if (i + j < size) {
                if (buffer[i + j] != 0) {
                    allZeroLine = 0;
                }
                if (buffer[i + j] != 0xFF) {
                    allFFLine = 0;
                }
            } else {
                printf(" ");
            }

            if (j % 8 == 7) {
                printf(" ");
            }
        }

        if (allZeroLine) {
            if (i + 16 < size) {
                if (buffer[i + 16] == 0) {
                    continue;  // 省略连续的全0行
                }
            } else {
                break;
            }
        }

        if (allFFLine) {
            if (i + 16 < size) {
                if (buffer[i + 16] == 0xFF) {
                    continue;  // 省略连续的全1行
                }
            } else {
                break;
            }
        }
			  printf("\n ");
            printf("%08zx: ", i);

        for (j = 0; j < 16; ++j) {
            if (i + j < size) {
                printf("%02x ", buffer[i + j]);
            } else {
                printf(" ");
            }

            if (j % 8 == 7) {
                //printf(" ");
            }
        }

        //printf(" ");

        //for (j = 0; j < 16; ++j) {
          //  if (i + j < size) {
            //    char c = buffer[i + j];
              //  printf("%c", (c >= 32 && c <= 126) ? c : '.');
          //  }
       // }

        
    }
}


int main() {
    const char* devicePath = "/dev/sda1";   // 设备路径
    // 只读方式打开设备
    int device = open(devicePath, O_RDONLY);
    if (device == -1) {
        perror("Failed to open device");
        return 1;
    }
    // 定义 deviceStats 结构体变量，用于存储设备的状态信息
    struct stat deviceStats;
    // 获取设备状态信息
    if (fstat(device, &deviceStats) == -1) {
        perror("Failed to get device stats");
        close(device);
        return 1;
    }
    
/// 超级块
    //读取超级块
    off_t offset = 1024;  // 超级块通常位于偏移量1024处
    char buffer[sizeof(struct ext_super_block)];
	 //printf("offset: %u\n",offset);
    ssize_t bytesRead = pread(device, buffer, sizeof(buffer), offset);
    if (bytesRead == -1) {
        perror("Failed to read superblock");
        close(device);
        return 1;
    }
    // 将 buffer 解释为 ext_super_block 结构体类型的指针 superblock
    struct ext_super_block* superblock = (struct ext_super_block*)buffer;
    // 块大小，byte转换为bit
    unsigned int block_size = 1 << (superblock->s_log_block_size + 10);
    unsigned int fragment_size = 1 << (superblock->s_log_frag_size + 10);
    // 打印
    printf("SUPERBLOCK\n");
    printf(" inode count: %u\n", superblock->s_inodes_count);
    printf(" block count: %u\n", superblock->s_blocks_count);
    printf(" reserved block count: %u\n", superblock->s_r_blocks_count);
    printf(" free blocks: %u\n", superblock->s_free_blocks_count);
    printf(" free indoes: %u\n", superblock->s_free_inodes_count);
    printf(" first block: %u\n", superblock->s_first_data_block);
    printf(" block size: %u\n", block_size);
    printf(" fragment size: %u\n", fragment_size);
    printf(" blocks per group: %u\n", superblock->s_blocks_per_group);
    printf(" fragements per group: %u\n", superblock->s_frags_per_group);
    printf(" inodes per group: %u\n", superblock->s_inodes_per_group);
    printf("\n");


/// 组描述符表
    // 获取组描述符表offset
    //offset += block_size;  // 组描述符表位于超级块之后一个块的位置
    //offset += 2;
    //offset += superblock->s_log_block_size;
    unsigned int group_desc_block = superblock->s_first_data_block + 1;
    off_t group_desc_table_offset = group_desc_block * block_size;

    // 读取组描述符表
    int groupDescTableSize = superblock->s_blocks_per_group * sizeof(struct ext_group_desc);   // 计算大小
    char groupDescBuffer[groupDescTableSize];

    bytesRead = pread(device, groupDescBuffer, groupDescTableSize, group_desc_table_offset);
    if (bytesRead == -1) {
        perror("Failed to read group descriptor table");
        close(device);
        return 1;
    }

    struct ext_group_desc* groupDescTable = (struct ext_group_desc*)groupDescBuffer;

    // 打印解析组描述符表
    printf("GROUP DESCRIPTOR TABLE\n");
    printf("offset: %lld\n", group_desc_table_offset);
    // 减去 1 是为了确保在除法运算中得到正确的组数，即使总块数不能被每个组的块数整除
    int numGroups = (superblock->s_blocks_count + superblock->s_blocks_per_group - 1) / superblock->s_blocks_per_group;
    printf("Group count: %u\n", numGroups);
    //for (int i = 0; i < numGroups; ++i) {
    //struct ext_group_desc* groupDesc = &groupDescTable[i];
    int i=0;
    struct ext_group_desc* groupDesc = &groupDescTable[i];
    printf("Group %d:\n", i);
    printf(" block bitmap block: %u\n", groupDesc->bg_block_bitmap_lo);
    printf(" inode bitmap block: %u\n", groupDesc->bg_inode_bitmap_lo);
    printf(" inode table block: %u\n", groupDesc->bg_inode_table_lo);
    printf(" free block count: %u\n", groupDesc->bg_free_blocks_count_lo);
    printf(" free inode count: %u\n", groupDesc->bg_free_inodes_count_lo);
    printf(" directory count: %u\n", groupDesc->bg_used_dirs_count_lo);
    printf("\n");



/// 位图
        printf("BITMAP\n");

        unsigned int bitmapBlockSize = block_size;

        //bitmapBlockSize <<= superblock->s_log_block_size;

        unsigned char* blockBitmap = malloc(bitmapBlockSize);
        if (!blockBitmap) {
            perror("Failed to allocate memory for block bitmap");
            close(device);
            return 1;
        }

        offset = groupDesc->bg_block_bitmap_lo * block_size;
        bytesRead = pread(device, blockBitmap, bitmapBlockSize, offset);
		 printf("offset: %u\n",offset);
        if (bytesRead == -1) {
            perror("Failed to read block bitmap");
            free(blockBitmap);
            close(device);
            return 1;
        }

        printf(" block bitmap:\n");
        printBitmap(blockBitmap, bitmapBlockSize);
        printf("\n");		 

        free(blockBitmap);

    //}


/// inode表项
    printf("INODE\n");
	struct stat inode;
    // 使用 stat 函数获取设备文件的相关信息，并将结果存储在 inode 结构体中
    if (stat(devicePath, &inode) == 0) {
        printf("Device ID: %ld\n", inode.st_dev);
        printf("Inode Number: %ld\n", inode.st_ino);
    } else {
        perror("stat"); // 打印与 stat 函数相关的错误信息
    }
   printf("\n");

    // 假设要读取第一个组的inode表
    unsigned int inodeTableBlock = groupDesc->bg_inode_table_lo;
    unsigned int inodeSize = sizeof(struct ext_inode);
    unsigned int numInodes = superblock->s_inodes_per_group;
    off_t inodeTableOffset = inodeTableBlock * block_size;

    // 读取inode表
    int inodeTableSize = numInodes * inodeSize;
    char inodeBuffer[inodeTableSize];
    bytesRead = pread(device, inodeBuffer, inodeTableSize, inodeTableOffset);
    if (bytesRead == -1) {
        perror("Failed to read inode table");
        close(device);
        return 1;
    }

    // 将缓冲区解释为inode结构数组
    struct ext_inode* inodeTable = (struct ext_inode*)inodeBuffer;

    // 打印解析inode表项
    printf("INODE TABLE\n");
	 printf("offset: %u\n",inodeTableOffset);
    //for (int i = 0; i < numInodes; ++i) {
    for (int i = 0; i < 40; ++i) {
        struct ext_inode* inode = &inodeTable[i];
		if(inode->i_size_lo!=0){
        printf("Inode %d:\n", i);
        printf(" mode: %x\n", inode->i_mode);
        printf(" uid: %u\n", inode->i_uid);
        printf(" size: %u\n", inode->i_size_lo);
        printf("\n");
		}
    }

    close(device);
    return 0;
}
